package com.wdl.datarest.implementation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;

import com.wdl.datarest.data.Alarm;
import com.wdl.datarest.data.AlarmType;

public class LogUtils {
    private static Logger log = LoggerFactory.getLogger("hushitong");
    private static Logger LOG = LoggerFactory.getLogger("LogUtils");

    private static String getTag(long personId) {
        Calendar cal = Calendar.getInstance();
        return "\"" + String.valueOf(personId % 10) + '.' + String.valueOf(cal.get(Calendar.YEAR)) + '.' + String.valueOf(cal.get(Calendar.MONTH) + 1) + "\"";
    }

    /**
     * Used to log alarm of UP, SIDE, AWAY, WET with AlarmType.
     */
    private static void logAlarm(long personId, AlarmType type, long raisedTime, long ackedTime) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + type.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + ",\"ackedTime\":" + (ackedTime / 1000) + "}");
    }

    /**
     * Used to log BREATHE alarms, need to record their values with time.
     */
    private static void logBreatheAlarm(long personId, long raisedTime, long ackedTime, long value) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.BREATHE.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + ",\"ackedTime\":" + (ackedTime / 1000) + ",\"value\":" + value + "}");
    }

    /**
     * Used to log HEART alarms, need to record their values with time.
     */
    private static void logHeartAlarm(long personId, long raisedTime, long ackedTime, long value) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.HEART.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + ",\"ackedTime\":" + (ackedTime / 1000) + ",\"value\":" + value + "}");
    }

    /**
     * Used to log HIST_MOVE, move number per hour.
     */
    public static void logMoveHistPerHour(long personId, long raisedTime, long value) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.HIST_MOVE.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + ",\"value\":" + value + "}");
    }

    /**
     * Used to log HIST_HEART data, average number per minutes
     */
    public static void logHeartHistData(long personId, long time, long value) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.HIST_HEART.ordinal() + ",\"raisedTime\":" + (time / 1000) + ",\"value\":" + value + "}");
    }

    /**
     * Used to log HIST_BREATHE data, average number per minutes
     */
    public static void logBreatheHistData(long personId, long time, long value) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.HIST_BREATHE.ordinal() + ",\"raisedTime\":" + (time / 1000) + ",\"value\":" + value + "}");
    }

    /**
     * Used to log LEFT alarm.
     */
    private static void logLeftAlarm(long personId, long raisedTime) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.LEFT.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + "}");
    }

    /**
     * Used to log RIGHT alarm.
     */
    private static void logRightAlarm(long personId, long raisedTime) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.RIGHT.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + "}");
    }

    /**
     * Used to log sleep status, raisedTime is in seconds.
     */
    public static void logSleepStatus(long personId, long raisedTime, long sleepHeavy, long sleepLight) {
        log.info("{\"tag\":" + getTag(personId) + ",\"personId\":" + personId + ",\"type\":" + AlarmType.SLEEP.ordinal() + ",\"raisedTime\":" + (raisedTime / 1000) + ",\"sleepHeavy\":" + sleepHeavy + ",\"sleepLight\":" + sleepLight + "}");
    }

    /**
     * Used to log alarm to elasticsearch.
     */
    public static void logAlarm(Alarm alarm) {
        switch (alarm.getType()) {
        case HEART:
            if (alarm.getAckedTime() > 0) {
                logHeartAlarm(alarm.getPersonId(), alarm.getRaisedTime(), alarm.getAckedTime(), alarm.getValue());
            }
            break;
        case BREATHE:
            if (alarm.getAckedTime() > 0) {
                logBreatheAlarm(alarm.getPersonId(), alarm.getRaisedTime(), alarm.getAckedTime(), alarm.getValue());
            }
            break;
        case LEFT:
            if (alarm.getAckedTime() <= 0) {
                // alarm was just acked, we only log this alarm when it just raises
                logLeftAlarm(alarm.getPersonId(), alarm.getRaisedTime());
            }
            break;
        case RIGHT:
            if (alarm.getAckedTime() <= 0) {
                // alarm was just acked, we only log this alarm when it just raises
                logRightAlarm(alarm.getPersonId(), alarm.getRaisedTime());
            }
            break;
        case UP:
        case SIDE:
        case AWAY:
        case WET:
        case MOVE:
        case DEVICE:
        case RING:
        case TURN_OVER:
            if (alarm.getAckedTime() > 0) {
                logAlarm(alarm.getPersonId(), alarm.getType(), alarm.getRaisedTime(), alarm.getAckedTime());
            }
            break;
        default:
            LOG.error("Alarm type " + alarm.getType() + " is not supported yet!");
        }
    }

    /**
     * Used to log unacked alarm to elasticsearch when clearing aging alarms.
     */
    public static void logNonAckedAlarm(Alarm alarm) {
        switch (alarm.getType()) {
        case HEART:
            logHeartAlarm(alarm.getPersonId(), alarm.getRaisedTime(), 0, alarm.getValue());
            break;
        case BREATHE:
            logBreatheAlarm(alarm.getPersonId(), alarm.getRaisedTime(), 0, alarm.getValue());
            break;
        case LEFT:
        case RIGHT:
            // We only log this alarm when it just raises
            break;
        case UP:
        case SIDE:
        case AWAY:
        case WET:
        case MOVE:
        case DEVICE:
        case RING:
            logAlarm(alarm.getPersonId(), alarm.getType(), alarm.getRaisedTime(), 0);
            break;
        default:
            LOG.error("Alarm type " + alarm.getType() + " is not supported yet!");
        }
    }
}